package top.cardone.security.shiro.authc.credential;

import lombok.Setter;
import org.apache.commons.lang3.math.NumberUtils;
import org.apache.shiro.authc.credential.PasswordService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import top.cardone.security.Descipher;

import java.util.Objects;

/**
 * Created by cardo on 2018/2/26 0026.
 */
public class DescipherPasswordServiceImpl implements PasswordService {
    @Setter
    private String separator = "：";

    @Setter
    private long validTimeout = 3600;

    @Setter
    private String defaultSalt = "cardone";

    @Autowired
    private Descipher descipher;

    @Override
    public String encryptPassword(Object plaintextPassword) {
        if (validTimeout > 0) {
            return this.descipher.encrypt(defaultSalt, plaintextPassword + this.separator + System.currentTimeMillis());
        }

        return this.descipher.encrypt(defaultSalt, String.valueOf(plaintextPassword));
    }

    @Override
    public boolean passwordsMatch(Object submittedPlaintext, String encrypted) {
        if (StringUtils.hasLength(encrypted)) {
            if (submittedPlaintext == null || submittedPlaintext.toString().isEmpty()) {
                return false;
            }
        } else {
            return submittedPlaintext == null || submittedPlaintext.toString().isEmpty();
        }

        String[] submittedPlaintextDecrypteds = top.cardone.context.util.StringUtils.split(this.descipher.decrypt(defaultSalt, submittedPlaintext.toString()), this.separator);

        if (submittedPlaintextDecrypteds.length > 1 && (validTimeout > 0)) {
            Long submittedPlaintextDecryptedTimeMillis = NumberUtils.toLong(submittedPlaintextDecrypteds[1], System.currentTimeMillis());

            if ((System.currentTimeMillis() - submittedPlaintextDecryptedTimeMillis) / 1000 > validTimeout) {
                return false;
            }
        }

        String[] decrypteds = top.cardone.context.util.StringUtils.split(this.descipher.decrypt(defaultSalt, encrypted), this.separator);

        return Objects.equals(submittedPlaintextDecrypteds[0], decrypteds[0]);
    }
}